package com.shuxian.algo;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class DeadLockTest {

    private static Object lock1 = new Object();
    private static Object lock2 = new Object();
    //flag保证线程之间的可见性
    private static volatile boolean flag1 = false;
    private static volatile boolean flag2 = false;

    public static void main(String[] args){
        new Thread(() ->{
            synchronized (lock1){
                System.out.println("线程1获得了lock1");
                flag1 = true;
                while(! flag2){
                    //线程2没有拿到lock2就等待
                    Thread.yield();
                }
                synchronized (lock2){
                    System.out.println("线程1获得了lock2");
                }
            }
        }, "t1").start();
        new Thread(() -> {
            synchronized (lock2){
                flag2 = true;
                System.out.println("线程2获得了lock2");
                while(! flag1){
                    Thread.yield();
                }
                synchronized (lock1){
                    System.out.println("线程1获得了lock1");
                }
            }
        }, "t2").start();

        //检测死锁
        checkDeadLock();
    }

    private static void checkDeadLock() {
        ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
        ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(1);
        //初始等待5秒，每个10秒检测一次
        scheduled.scheduleAtFixedRate(() ->{
            long[] deadlockedThreads = mxBean.findDeadlockedThreads();
            if (deadlockedThreads != null){
                System.out.println("检测到死锁");
                ThreadInfo[] threadInfos = mxBean.getThreadInfo(deadlockedThreads);
                for (ThreadInfo info : threadInfos) {
                    System.out.println(info.getThreadId() + "：" + info.getThreadName());
                }
            }
        }, 5L, 10L, TimeUnit.SECONDS);
    }
}
